package com.housekeeping.controller.api;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.housekeeping.model.User;
import com.housekeeping.service.UserService;
import com.housekeeping.service.impl.UserServiceImpl;
import com.housekeeping.utils.ApiResponse;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 用户认证模块控制器
 */
@WebServlet("/api/users/*")
public class UserApiController extends HttpServlet {
    
    private UserService userService = new UserServiceImpl();
    private ObjectMapper objectMapper = new ObjectMapper();
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        String pathInfo = req.getPathInfo();
        
        try {
            if (pathInfo == null || pathInfo.equals("/")) {
                handleGetAllUsers(req, resp);
            } else if (pathInfo.equals("/me")) {
                handleGetCurrentUser(req, resp);
            } else if (pathInfo.matches("/\\d+")) {
                handleGetUserById(req, resp);
            } else if (pathInfo.equals("/customers")) {
                handleGetCustomers(req, resp);
            } else if (pathInfo.equals("/staff")) {
                handleGetStaff(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        try {
            handleCreateUser(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        String pathInfo = req.getPathInfo();
        
        try {
            if (pathInfo != null && pathInfo.matches("/\\d+")) {
                handleUpdateUser(req, resp);
            } else if (pathInfo != null && pathInfo.matches("/\\d+/password")) {
                handleChangePassword(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        String pathInfo = req.getPathInfo();
        
        try {
            if (pathInfo != null && pathInfo.matches("/\\d+")) {
                handleDeleteUser(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }
    
    private void handleGetAllUsers(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        List<User> users = userService.getAllUsers();

        for (User user : users) {
            user.setPassword(null);
        }
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(users));
    }
    
    private void handleGetUserById(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        int userId = Integer.parseInt(pathInfo.substring(1));
        
        User user = userService.getUserById(userId);
        if (user != null) {
            user.setPassword(null);
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(user));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "User not found"));
        }
    }

    private void handleGetCurrentUser(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        

        User user = userService.getUserById(currentUser.getUserId());
        if (user != null) {
            user.setPassword(null);
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(user));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "User not found"));
        }
    }
    
    private void handleGetCustomers(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        List<User> customers = userService.getCustomers();
        for (User customer : customers) {
            customer.setPassword(null);
        }
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(customers));
    }
    
    private void handleGetStaff(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        List<User> staff = userService.getStaff();
        for (User staffMember : staff) {
            staffMember.setPassword(null);
        }
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(staff));
    }
    
    private void handleCreateUser(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            
            Map<String, Object> userData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            
            User user = new User();
            user.setUsername((String) userData.get("username"));
            user.setPassword((String) userData.get("password"));
            user.setRealName((String) userData.get("realName"));
            user.setPhone((String) userData.get("phone"));
            user.setEmail((String) userData.get("email"));
            user.setAddress((String) userData.get("address"));
            user.setUserType((Integer) userData.get("userType"));
            
            if (userService.register(user)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("User created successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to create user"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }

    private void handleUpdateUser(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        int userId = Integer.parseInt(pathInfo.substring(1));
        
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            
            Map<String, Object> userData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            
            User user = userService.getUserById(userId);
            if (user == null) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "User not found"));
                return;
            }
            

            if (userData.get("realName") != null) {
                user.setRealName((String) userData.get("realName"));
            }
            if (userData.get("phone") != null) {
                user.setPhone((String) userData.get("phone"));
            }
            if (userData.get("email") != null) {
                user.setEmail((String) userData.get("email"));
            }
            if (userData.get("address") != null) {
                user.setAddress((String) userData.get("address"));
            }
            if (userData.get("userType") != null) {
                user.setUserType((Integer) userData.get("userType"));
            }
            if (userData.get("status") != null) {
                user.setStatus((Integer) userData.get("status"));
            }
            
            if (userService.updateUser(user)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("User updated successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to update user"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }

    private void handleChangePassword(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        String[] parts = pathInfo.split("/");
        int userId = Integer.parseInt(parts[1]);
        
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            
            Map<String, Object> passwordData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            
            String newPassword = (String) passwordData.get("password");
            if (newPassword == null || newPassword.trim().isEmpty()) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Password cannot be empty"));
                return;
            }
            
            User user = userService.getUserById(userId);
            if (user == null) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "User not found"));
                return;
            }
            
            user.setPassword(newPassword);
            if (userService.updateUser(user)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("Password changed successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to change password"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }

    private void handleDeleteUser(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        int userId = Integer.parseInt(pathInfo.substring(1));
        
        User user = userService.getUserById(userId);
        if (user == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "User not found"));
            return;
        }
        
        if (userService.deleteUser(userId)) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("User deleted successfully"));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to delete user"));
        }
    }
} 